package Data.DAO;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DataStore implements IDataStore {

    Class readClass;
    File file;

    public DataStore(Class readClass, File file) {
        this.readClass = readClass;
        this.file = file;
    }

    public List getObjects() {
        ArrayList<Object> list = new ArrayList<Object>();
        try {
            if (file.exists()) {
                ObjectInputStream ois = null;
                try {
                    ois = new ObjectInputStream(new FileInputStream(file));
                    Object tmp = ois.readObject();
                    list = (ArrayList<Object>) tmp;
                    //list = (ArrayList<Object>) ois.readObject();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    ois.close();
                    return list;
                }
            } else {
                return list;
            }
        } catch (Exception e) {
            e.printStackTrace();;
            return list;
        }
    }

    public void update(List list) {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(file));
            oos.writeObject(list);
            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void add(List list) {
        try {
            List newList = getObjects();
            newList.addAll(list);
            update(newList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List getObjectsByAttr(String key, String value) {
        return searchObjectsByAttr(key, "^" + value + "$");
    }

    public List searchObjectsByAttr(String key, String regexp) {
        ArrayList<Object> list = new ArrayList<Object>();
        try {
            ArrayList<Object> allList = (ArrayList<Object>) getObjects();
            String methodName = "get" + key.substring(0, 1).toUpperCase() + key.substring(1);
            Method method = readClass.getMethod(methodName);
            Class type = method.getReturnType();
            for (Object obj : allList) {
                String result = typeToString(type, method.invoke(readClass.cast(obj)));
                Pattern pattern = Pattern.compile(regexp);
                Matcher matcher = pattern.matcher(result);
                if (matcher.matches()) {
                    list.add(obj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return list;
        }
    }

    private String typeToString(Class type, Object obj) {
        try {
            if (Date.class.equals(type)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                return sdf.format((Date) obj);
            } else {
                return obj.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public void deleteByIndex(int[] index) {
        try {
            List list = getObjects();
            for (int i = 0; i < index.length; i++) {
                list.remove(index[i]);
            }
            update(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
